const upload = require("../middleware/upload");
const dbConfig = require("../config/db");
const sharp = require("sharp");

const MongoClient = require("mongodb").MongoClient;
const GridFSBucket = require("mongodb").GridFSBucket;
const ObjectId = require("mongodb").ObjectId;

const url = dbConfig.url;

const baseUrl = "http://localhost:8080/files/";

const mongoClient = new MongoClient(url);

const uploadFiles = async (req, res) => {
  try {
    // 上传图片到multer 中间件
    await upload(req, res);
    console.log(req.files);

    // 如果没有文件
    if (req.files.length <= 0) {
      return res
        .status(400)
        .send({ message: "You must select at least 1 file." });
    }

    // 链接数据库
    await mongoClient.connect();
    const database = mongoClient.db(dbConfig.database);
    const bucket = new GridFSBucket(database, {
      bucketName: dbConfig.imgBucket,
    });

    // 从数据库中挨个读取文件，并用sharp读取图片的宽高，将宽高信息写入数据库
    for (let i = 0; i < req.files.length; i++) {
      const { id } = req.files[i];

      // 从数据库中根据id查找图片，并用sharp读取图片的宽高
      const stream = bucket.openDownloadStream(id);
      const chunks = [];
      stream.on("data", (chunk) => {
        chunks.push(chunk);
      });
      stream.on("end", () => {
        const buffer = Buffer.concat(chunks);
        sharp(buffer)
          .metadata()
          .then(({ width, height }) => {
            console.log(width, height);
            // 将 宽、高、更新时间 写入数据库
            database.collection(dbConfig.imgBucket + ".files").updateOne(
              { _id: id },
              {
                $set: {
                  width: width,
                  height: height,
                },
              }
            );
          });
      });
    }

    // 返回成功信息
    return res.status(200).send({
      message: "Files have been uploaded.",
    });
  } catch (error) {
    console.log(error);

    if (error.code === "LIMIT_UNEXPECTED_FILE") {
      return res.status(400).send({
        message: "Too many files to upload.",
      });
    }
    return res.status(500).send({
      message: `Error when trying upload many files: ${error}`,
    });
  }
};

// 获取文件列表 所有文件
const getListFiles = async (req, res) => {
  try {
    await mongoClient.connect();

    const database = mongoClient.db(dbConfig.database);
    const images = database.collection(dbConfig.imgBucket + ".files");

    const cursor = images.find({});

    if ((await cursor.count()) === 0) {
      // return res.status(500).send({
      //   message: "No files found!",
      // });

      return res.status(200).send([]);
    }

    let fileInfos = [];
    await cursor.forEach((doc) => {
      fileInfos.push({
        name: doc.filename,
        url: baseUrl + doc.filename,
        metadata: doc.metadata,
      });
    });

    return res.status(200).send(fileInfos);
  } catch (error) {
    return res.status(500).send({
      message: error.message,
    });
  }
};

// 查询文件列表 分页
// 1.模糊查询 查询条件有文件名 2.精确查询 查询条件有文件名 文件类型 文件大小 上传时间
const getListFilesPage = async (req, res) => {
  // 获取分页参数
  const { page = 1, pageSize = 10, ...query } = req.query;
  try {
    // 连接数据库
    await mongoClient.connect();
    const database = mongoClient.db(dbConfig.database);
    const images = database.collection(dbConfig.imgBucket + ".files");

    // 需要模糊查询的字段列表
    const fuzzyFields = ["filename"];

    const search = {};
    // 添加模糊查询条件
    fuzzyFields.forEach((field) => {
      if (query[field]) {
        search[field] = { $regex: query[field], $options: "i" };
      }
    });

    // 分页处理
    const skip = (page - 1) * Number(pageSize);
    const limit = Number(pageSize);

    // 执行查询 按插入时间倒序
    const cursor = images
      .find(search)
      .sort({ weight: -1 }) // 按权重 倒序
      .skip(skip)
      .limit(limit);

    // 获取总记录数、总页数、当前页码、每页数量、当前页数据
    const total = await images.countDocuments(search);
    const totalPage = Math.ceil(total / Number(pageSize));
    const numPage = Number(page);
    const numPageSize = Number(pageSize);

    // 获取当前页数据
    let fileInfos = [];
    await cursor.forEach(({ filename, _id, width, height, weight }) => {
      fileInfos.push({
        id: _id,
        filename,
        width,
        height,
        src: `${baseUrl}${_id}`,
        weight,
      });
    });

    console.log(fileInfos);
    if (fileInfos.length === 0) {
      return res.status(200).send({
        data: [],
        total,
        totalPage,
        page: numPage,
        pageSize: numPageSize,
      });
    }

    return res.status(200).send({
      data: fileInfos,
      total,
      totalPage,
      page: numPage,
      pageSize: numPageSize,
    });
  } catch (error) {
    return res.status(500).send({
      message: error.message,
    });
  }
};

// 根据文件Id下载文件
const download = async (req, res) => {
  try {
    await mongoClient.connect();

    const database = mongoClient.db(dbConfig.database);
    const bucket = new GridFSBucket(database, {
      bucketName: dbConfig.imgBucket,
    });

    const objId = new ObjectId(req.params.id);
    let downloadStream = bucket.openDownloadStream(objId);

    downloadStream.on("data", function (data) {
      return res.status(200).write(data);
    });

    downloadStream.on("error", function (err) {
      return res.status(404).send({ message: "Cannot download the Image!" });
    });

    downloadStream.on("end", () => {
      return res.end();
    });
  } catch (error) {
    return res.status(500).send({
      message: error.message,
    });
  }
};

// 权重修改接口
const updateImageWeightByWeight = async (req, res) => {
  try {
    await mongoClient.connect();
    const database = mongoClient.db(dbConfig.database);
    const images = database.collection(dbConfig.imgBucket + ".files");
    const { id, weight } = req.body;

    if (!id || !weight) {
      return res.status(400).send({
        message: "Please provide id and weight",
      });
    }
    images.updateOne(
      { _id: new ObjectId(id) },
      { $set: { weight: weight } },
      (err, result) => {
        if (err) {
          console.log(err);
          return res.status(500).send({
            message: "Error updating image weight",
          });
        }
        return res.status(200).send({
          message: "Image weight updated successfully",
          result,
        });
      }
    );
  } catch (error) {
    console.log(error);
  }
};

// 根据ids查询图片列表
const getImageListByIds = async (req, res) => {
  const maxIds = dbConfig.MAX_IDS;

  try {
    await mongoClient.connect();
    const database = mongoClient.db(dbConfig.database);
    const images = database.collection(dbConfig.imgBucket + ".files");
    const { ids } = req.body;

    if (!Array.isArray(ids)) {
      return res.status(400).send({
        message: "ids must be an array",
      });
    }

    if (ids.length === 0) {
      return res.status(200).send({
        data: [],
        message: '无数据'
      });
    }

    if (ids.length > maxIds) {
      return res.status(400).send(`最多只能请求 ${maxIds} 个图片`);
    }

    images.find({ _id: { $in: ids.map((id) => new ObjectId(id)) } }).toArray((err, data) => {
      if (err) {
        console.log(err);
        return res.status(500).send({
          message: "Error getting image list",
        });
      }

      let fileInfos = data.map(({ filename, _id, width, height, weight }) => {
        return {
          id: _id,
          filename,
          width,
          height,
          src: `${baseUrl}${_id}`,
          weight,
        };
      })

      return res.status(200).send({
        message: "Image list retrieved successfully",
        data: fileInfos,
      });
    });
  } catch (error) {
    console.log(error);
  }
}

module.exports = {
  uploadFiles,
  getListFiles,
  getListFilesPage,
  download,
  updateImageWeightByWeight,
  getImageListByIds
};
